﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;

namespace WooCoo.ObjectModel
{
    public abstract partial class Entity : ITrackStatus
    {
        private PersistenceStatus _status = PersistenceStatus.New;

        /// <summary>
        /// 实体的数据状态
        /// </summary>
        public PersistenceStatus Status
        {
            get { return this._status; }
            set { this._status = value; }
        }

        [IgnoreDataMember]
        internal bool IsNew
        {
            get { return this._status == PersistenceStatus.New; }
        }

        [IgnoreDataMember]
        internal bool IsSelfDirty
        {
            get { return this._status != PersistenceStatus.Unchanged; }
        }

        [IgnoreDataMember]
        /// <summary>
        /// 本身是否可用
        /// </summary>
        internal bool IsSelfValid
        {
            get { return this.ValidationRules.BrokenRules.Count() == 0; }
        }

        [IgnoreDataMember]
        internal bool IsDeleted
        {
            get { return this._status == PersistenceStatus.Deleted; }
        }

        internal bool IsDirty
        {
            get
            {
                if (this.IsSelfDirty || (this.FieldDataManager != null && this.FieldDataManager.IsDirty()))
                    return true;
                return false;
            }
        }

        internal bool IsValid
        {
            get
            {
                if (!this.IsSelfValid)
                    return false;
                foreach (var item in this.FieldDataManager.GetDirtyFieldDatas())
                {
                    if (item.Value is ITrackStatus && !(item as ITrackStatus).IsValid)
                        return false;
                }
                return true;
            }
        }

        #region ITrackStatus

        [IgnoreDataMember]
        bool ITrackStatus.IsDirty
        {
            get { return this.IsDirty; }
        }

        [IgnoreDataMember]
        /// <summary>
        /// 是否可用，包含检测子对象
        /// </summary>
        bool ITrackStatus.IsValid
        {
            get { return this.IsValid; }   
        }

        //public bool IsChild
        //{
        //    get;
        //    private set;
        //}

        void ITrackStatus.MarkClean()
        {
            this.MarkClean();
        }

        protected void MarkClean()
        {
            this._status = PersistenceStatus.Unchanged;
            if (this.FieldDataManager != null)
                this.FieldDataManager.MarkClean();
        }

        #endregion

        protected virtual void MarkNew()
        {
            this._status = PersistenceStatus.New;
        }

        /// <summary>
        /// 标识对象为脏数据，表示发生过数据变化.
        /// </summary>
        /// <remarks>
        /// <para>
        /// 一般在对象内部数据发生变化后，调用该方法。
        /// </para><para>
        /// 该方法通过框架内部进行标识，或者通过.Net控件的数据绑定事件触发方法中
        /// 会调用本方法，以控制数据变化标记的准确性。       
        /// </para>
        /// </remarks>
        protected virtual void MarkDirty()
        {
            if (this._status == PersistenceStatus.Unchanged)
                this._status = PersistenceStatus.Modified;
        }
        /// <summary>
        /// 将数据状态变更为Unchanged状态，但实际数据值不发生回退。
        /// </summary>
        protected virtual void MarkOld()
        {
            this._status = PersistenceStatus.Unchanged;
            foreach (var field in this.GetDirtyFieldDatas())
            {
                field.MarkClean();
            }
        }
        /// <summary>
        /// 将数据状态变更为删除状态,子对角不做删除标记
        /// </summary>
        protected virtual void MarkDeleted()
        {
            this._status = PersistenceStatus.Deleted;
            foreach(var field in this.FieldDataManager.GetChildEntity())
            {
                (field as IEntityOrList).DeleteChild();
            }
        }
        /// <summary>
        /// 标记自身为子对象
        /// </summary>
        //protected void MarkAsChild()
        //{
        //    this.IsChild = true;
        //}
        /// <summary>
        /// 标记为删除，一般由父对象调用
        /// </summary>
    }
}
